package com.zyc.auto;

import com.zyc.pojo.Table;
import com.zyc.pojo.TableProperty;
import com.zyc.util.HappyUtil;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

public class AutoPojoMapper {
    private final String namespace = HappyUtil.properties.getProperty("namespace");

    public void start() throws IOException {
        autoPojo();
        autoMapper();
        autoXml();
    }

    /**
     * 自动生成pojo
     */
    private void autoPojo() throws IOException {
        List<Table> tableList = HappyUtil.getTableList();
        String pathStr = HappyUtil.properties.getProperty("targetPath");
        for (Table table : tableList) {
            String className = table.getTableUpperCamelName();
            StringBuilder pojoText = new StringBuilder();
            pojoText.append("package ").append(HappyUtil.properties.getProperty("namespace")).append(".pojo;\n")
                    .append("import lombok.AllArgsConstructor;\n" +
                            "import com.alibaba.fastjson.annotation.JSONField;\n" +
                            "import com.fasterxml.jackson.annotation.JsonFormat;\n" +
                            "import io.swagger.annotations.ApiModelProperty;\n" +
                            "import io.swagger.annotations.ApiModel;\n" +
                            "import lombok.Data;\n" +
                            "import lombok.NoArgsConstructor;\n" +
                            "import lombok.experimental.Accessors;\n" +
                            "import java.math.BigDecimal;\n" +
                            "import java.util.Date;\n" +
                            "import java.util.Map;\n" +
                            "@Data\n" +
                            "@AllArgsConstructor\n" +
                            "@NoArgsConstructor\n" +
                            "@Accessors(chain = true)\n" +
                            "@ApiModel(\"返回的").append(className)
                    .append("对象\")\n" +
                            "public class ").append(className).append(" {\n");
            for (TableProperty tableProperty : table.getTableProperties()) {
                String comment = tableProperty.getComment();
                if (comment != null && !("".equals(comment))) {
                    pojoText.append("@ApiModelProperty(\"").append(comment).append("\")\n");
                }
                if ("Date".equals(tableProperty.getJavaType())) {
                    pojoText.append("@JsonFormat(pattern= \"yyyy-MM-dd HH:mm:ss\",timezone = \"GMT+8\")\n");
                    pojoText.append("@JSONField(format = \"yyyy-MM-dd HH:mm:ss\")\n");
                }
                pojoText.append("private ").append(tableProperty.getJavaType()).append(" ").append(tableProperty.getPropertyLowerCamelName()).append(";\n");
            }
            pojoText.append("@ApiModelProperty(\"排序方式\")\n");
            pojoText.append("private Map<String, Integer> orderBy;\n");


            pojoText.append("}\n");
            File path = new File(pathStr + "/pojo");
            if (!path.exists() && !path.mkdirs()) {
                System.err.println("文件夹生成错误！" + path);
                return;
            }
            File file = new File(pathStr + "/pojo/" + className + ".java");
            System.out.println(file.getAbsolutePath());
            FileWriter fw = new FileWriter(file);
            fw.write(pojoText.toString());
            HappyUtil.closeAll(fw);
        }
    }

    /**
     * 自动生成mapper
     */
    private void autoMapper() throws IOException {
        List<Table> tableList = HappyUtil.getTableList();
        String pathStr = HappyUtil.properties.getProperty("targetPath");
        for (Table table : tableList) {
            //获得主键
            TableProperty primaryKey = table.getPrimaryKey();
            //主键属性
            String javaType = primaryKey.getJavaType();
            //小驼峰名
            String propertyLowerCamelName = primaryKey.getPropertyLowerCamelName();
            String className = table.getTableUpperCamelName();
            String pojoName = table.getTableLowerCamelName();
            File path = new File(pathStr + "/mapper");
            if (!path.exists() && !path.mkdirs()) {
                System.err.println("文件夹生成错误！" + path);
                return;
            }
            File file = new File(pathStr + "/mapper/" + className + "Mapper.java");
            System.out.println(file.getAbsolutePath());
            FileWriter fw = new FileWriter(file);
            String mapperText = "package " + HappyUtil.properties.getProperty("namespace") + ".mapper;\n" +
                    "import " + namespace + ".pojo." + table.getTableUpperCamelName() + ";\n" +
                    "import org.springframework.stereotype.Component;\n" +
                    "import java.util.List;\n" +
                    "@Component\n" +
                    "public interface " + className + "Mapper {\n" +
                    "List<" + className + "> selectByCondition(" + className + " " + pojoName + ");\n" +
                    className + " selectByOne(" + className + " " + pojoName + ");\n" +
                    "List<" + className + "> selectByOrder(" + className + " " + pojoName + ");\n" +
                    "List<" + className + "> selectAll();\n" +
                    className + " selectById(" + javaType + " " + propertyLowerCamelName + ");\n" +
                    "List<" + className + "> simpleSelectByCondition(" + className + " " + pojoName + ");\n" +
                    className + " simpleSelectByOne(" + className + " " + pojoName + ");\n" +
                    "List<" + className + "> simpleSelectAll();\n" +
                    className + " simpleSelectById(" + javaType + " " + propertyLowerCamelName + ");\n" +
                    "int insert(List<" + className + "> list);\n" +
                    "int insertOne(" + className + " " + pojoName + ");\n" +
                    "int update(" + className + " " + pojoName + ");\n" +
                    "int delete(String[] ids);\n" +
                    "int deleteOne(String id);\n}";
            fw.write(mapperText);
            HappyUtil.closeAll(fw);
        }
    }

    /**
     * 自动生成xml
     */
    private void autoXml() throws IOException {
        List<Table> tableList = HappyUtil.getTableList();
        String pathStr = HappyUtil.properties.getProperty("targetPath");
        for (Table table : tableList) {
            String className = table.getTableUpperCamelName();
            String pojoName = table.getTableLowerCamelName();
            String tableName = "`" + table.getTablePascalName() + "`";
            String primaryKey = table.getPrimaryKey().getPropertyPascalName();
            String javaKey = table.getPrimaryKey().getPropertyLowerCamelName();
            List<TableProperty> tableProperties = table.getTableProperties();
            StringBuilder xmlText = new StringBuilder();
            xmlText.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
                    "<!DOCTYPE mapper\n" +
                    "PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n" +
                    "\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n" +
                    "<mapper namespace=\"").append(namespace).append(".mapper.").append(className).append("Mapper\">\n");
            xmlText.append("<resultMap id=\"").append(className).append("Map\" type=\"").append(className).append("\">\n");
            StringBuilder sb = new StringBuilder();
            for (TableProperty tableProperty : tableProperties) {
                if (tableProperty == table.getPrimaryKey()) {
                    xmlText.append("<id property=\"").append(javaKey).append("\" column=\"").append(primaryKey).append("\"/>\n");
                } else {
                    sb.append("<result property=\"").append(tableProperty.getPropertyLowerCamelName()).append("\" column=\"").append(tableProperty.getPropertyPascalName()).append("\"/>\n");
                }
            }
            xmlText.append(sb);
            xmlText.append("</resultMap>\n");

            xmlText.append("<resultMap id=\"Simple").append(className).append("Map\" type=\"").append(className).append("\">\n");
            sb = new StringBuilder();
            for (TableProperty tableProperty : tableProperties) {
                if (tableProperty == table.getPrimaryKey()) {
                    xmlText.append("<id property=\"").append(javaKey).append("\" column=\"").append(primaryKey).append("\"/>\n");
                } else {
                    sb.append("<result property=\"").append(tableProperty.getPropertyLowerCamelName()).append("\" column=\"").append(tableProperty.getPropertyPascalName()).append("\"/>\n");
                }
            }
            xmlText.append(sb);
            xmlText.append("</resultMap>\n");
            //selectByCondition
            xmlText.append("<select id=\"selectByCondition\" resultMap=\"").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",").append("\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n" +
                    "<trim prefix=\"where\" prefixOverrides=\"and\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(name).append(" != null\">\n")
                        .append("and ").append(tableName).append(".").append(HappyUtil.camelToPascal(name)).append(" = #{").append(name).append("}\n</if>\n");
            }
            xmlText.append("</trim>\n" +
                    "</select>\n\n");
            //selectByOneCondition
            xmlText.append("<select id=\"selectByOne\" resultMap=\"").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",").append("\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n" +
                    "<trim prefix=\"where\" prefixOverrides=\"and\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(name).append(" != null\">\n")
                        .append("and ").append(tableName).append(".").append(HappyUtil.camelToPascal(name)).append(" = #{").append(name).append("}\n</if>\n");
            }
            xmlText.append("</trim>\n" +
                    "</select>\n\n");

            //selectByOrder
            xmlText.append("<select id=\"selectByOrder\" resultMap=\"").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",").append("\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n" +
                    "<trim prefix=\"where\" prefixOverrides=\"and\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(name).append(" != null\">\n")
                        .append("and ").append(tableName).append(".").append(HappyUtil.camelToPascal(name)).append(" = #{").append(name).append("}\n</if>\n");
            }
            xmlText.append("</trim>\n");
            xmlText.append("<trim prefix=\"order by\" suffixOverrides=\",\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"orderBy.")
                        .append(name)
                        .append(" != null\">\n");
                xmlText.append(tableName)
                        .append(".")
                        .append(HappyUtil.camelToPascal(name))
                        .append("\n");
                xmlText.append("<if test=\"orderBy.")
                        .append(name)
                        .append(" == 1\">\n");
                xmlText.append("DESC\n");
                xmlText.append("</if>\n");
                xmlText.append(",\n");
                xmlText.append("</if>\n");
            }
            xmlText.append("</trim>\n");
            xmlText.append("</select>\n\n");

            //selectById
            xmlText.append("<select id=\"selectById\" resultMap=\"").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\nwhere ").append(tableName)
                    .append(".").append(primaryKey).append(" = #{").append(javaKey).append("}").append("\n</select>").append("\n\n");

            //selectAll
            xmlText.append("<select id=\"selectAll\" resultMap=\"").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n</select>").append("\n\n");

            xmlText.append("<select id=\"simpleSelectByCondition\" resultMap=\"Simple").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n" +
                    "<trim prefix=\"where\" prefixOverrides=\"and\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(name).append(" != null\">\n")
                        .append("and ").append(tableName).append(".").append(HappyUtil.camelToPascal(name)).append(" = #{").append(name).append("}\n</if>\n");
            }
            xmlText.append("</trim>\n" +
                    "</select>\n\n");

            xmlText.append("<select id=\"simpleSelectByOne\" resultMap=\"Simple").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n" +
                    "<trim prefix=\"where\" prefixOverrides=\"and\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(name).append(" != null\">\n")
                        .append("and ").append(tableName).append(".").append(HappyUtil.camelToPascal(name)).append(" = #{").append(name).append("}\n</if>\n");
            }
            xmlText.append("</trim>\n" +
                    "</select>\n\n");

            //selectById
            xmlText.append("<select id=\"simpleSelectById\" resultMap=\"Simple").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\nwhere ").append(tableName)
                    .append(".").append(primaryKey).append(" = #{").append(javaKey).append("}").append("\n</select>").append("\n\n");

            //selectAll
            xmlText.append("<select id=\"simpleSelectAll\" resultMap=\"Simple").append(className).append("Map\">\n" +
                    "select ");
            for (TableProperty tableProperty : tableProperties) {
                String name = tableProperty.getPropertyPascalName();
                xmlText.append(tableName).append(".").append(name).append(",\n");
            }
            xmlText.deleteCharAt(xmlText.length() - 2);
            xmlText.append(" from ").append(tableName).append(" ").append(tableName).append("\n</select>").append("\n\n");

            xmlText.append("<delete id=\"delete\">\n" + "delete from ").append(tableName)
                    .append(" where ").append(primaryKey).append(" in\n" +
                    "<foreach collection=\"array\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n" +
                    "#{id}\n" +
                    "</foreach>\n" +
                    "</delete>\n\n");

            xmlText.append("<delete id=\"deleteOne\">\n" + "delete from ").append(tableName)
                    .append(" where ").append(primaryKey).append(" = #{id}\n" +
                    "</delete>\n\n");

            xmlText.append("<update id=\"update\">\nupdate ").append(tableName).append("\n" +
                    "<trim prefix=\"set\" suffixOverrides=\",\">\n");

            for (TableProperty tableProperty : tableProperties) {
                if (tableProperty == table.getPrimaryKey()) {
                    continue;
                }
                String propertyName = tableProperty.getPropertyLowerCamelName();
                String propertyTableName = tableProperty.getPropertyPascalName();
                xmlText.append("<if test=\"").append(propertyName).append(" != null\">\n")
                        .append(propertyTableName).append(" = #{").append(propertyName).append("},\n</if>\n");
            }

            xmlText.append(primaryKey).append(" = #{").append(javaKey).append("}\n" +
                    "</trim>\nwhere ").append(primaryKey).append(" = #{").append(javaKey).append("}\n</update>\n\n" +
                    "<insert id=\"insert\">\ninsert into ").append(tableName).append(" values\n")
                    .append("<foreach collection=\"list\" item=\"").append(pojoName).append("\" separator=\",\">\n(");

            boolean sign = true;
            for (TableProperty tableProperty : tableProperties) {
                if (sign) {
                    sign = false;
                } else {
                    xmlText.append(",").append("\n");
                }
                String name = tableProperty.getPropertyLowerCamelName();
                xmlText.append("#{").append(pojoName).append(".").append(name).append("}");
            }

            xmlText.append(")\n" +
                    "</foreach>\n" +
                    "</insert>\n");

            xmlText.append("<insert id=\"insertOne\">\ninsert into ").append(tableName)
                    .append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");

            for (TableProperty tableProperty : tableProperties) {
                String propertyName = tableProperty.getPropertyLowerCamelName();
                String propertyTableName = tableProperty.getPropertyPascalName();
                xmlText.append("<if test=\"").append(propertyName).append(" != null\">\n")
                        .append(propertyTableName).append(",\n</if>\n");
            }

            xmlText.append("</trim>\n");
            xmlText.append(" values\n" +
                    "<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
            for (TableProperty tableProperty : tableProperties) {
                String propertyName = tableProperty.getPropertyLowerCamelName();
                xmlText.append("<if test=\"").append(propertyName).append(" != null\">\n")
                        .append("#{").append(propertyName).append("},\n</if>\n");
            }
            xmlText.append("</trim>\n");
            xmlText.append("</insert>\n");
            xmlText.append("</mapper>");

            File path = new File(pathStr + "/xml");
            if (!path.exists() && !path.mkdirs()) {
                System.err.println("文件夹生成错误！" + path);
                return;
            }
            File file = new File(pathStr + "/xml/" + className + "Mapper.xml");
            System.out.println(file.getAbsolutePath());
            FileWriter fw = new FileWriter(file);
            fw.write(xmlText.toString());
            HappyUtil.closeAll(fw);
        }
    }
}
